#include "pch.h"
#include "PointCloud.h"
#include "DXFReader.h"
#include "PointCloudHandler.h"
using namespace AutomatedSurfaceReconstruction;

CPointCloud::CPointCloud(QObject* vParent) : QObject(vParent)
{
	
}

std::string CPointCloud::__getSuffix(const std::string& vFilePath)
{
	return vFilePath.substr(vFilePath.find_last_of('.') + 1);
}

std::string CPointCloud::__getOnlyFileName(const std::string& vFileName, const std::string& vFileSuffix,const std::unordered_map<std::string, PCLPointSetType::Ptr>& vFilePath2PointCloud)
{
	std::string OnlyFileName = vFileName;
	int i = 0;

	if (vFileSuffix == "las")
	{
		while (vFilePath2PointCloud.count(OnlyFileName))
		{
			OnlyFileName = vFileName.substr(0, vFileName.find_last_of('.')) + "(" + std::to_string(++i) + ")." + vFileSuffix;
		}
	}
	else
	{
		if (vFileSuffix == "obj")
		{
			while (vFilePath2PointCloud.count(OnlyFileName))
			{
				OnlyFileName = vFileName.substr(0, vFileName.find_last_of('.')) + "(" + std::to_string(++i) + ")." + vFileSuffix;
			}
		}
	}
	return OnlyFileName;
}

void CPointCloud::onActionLoadPointCloud(std::vector<std::string> vFilePathSet, std::unordered_map<std::string, PCLPointSetType::Ptr> vioFilePath2PointCloud)
{
	std::vector<std::string> FileNameSet;

	foreach(std::string FilePath, vFilePathSet)
	{
		std::string FileSuffix = __getSuffix(FilePath);
		std::string FileName = __getOnlyFileName(FilePath, FileSuffix, vioFilePath2PointCloud);
		FileNameSet.push_back(FileName);
		PCLPointSetType::Ptr PCLPointSet = make_shared<PCLPointSetType>();

		if (vFilePathSet.empty())return;
		std::ifstream Ifstream;
		Ifstream.open(FilePath, std::ios::in | std::ios::binary);
		liblas::ReaderFactory Factory;
		liblas::Reader Reader = Factory.CreateWithStream(Ifstream);
		liblas::Header const& Header = Reader.GetHeader();
		size_t PointCloudSize = Header.GetPointRecordsCount();

		PCLPointSet->resize(PointCloudSize);
		PCLPointSet->width = PointCloudSize;
		PCLPointSet->height = 1;
		PCLPointSet->is_dense = true;
		for (size_t i = 0; i < PointCloudSize; i++)
		{
			Reader.ReadNextPoint();
			liblas::Point const& Point = Reader.GetPoint();
			PCLPointSet->points[i].x = Point.GetX();
			PCLPointSet->points[i].y = Point.GetY();
			PCLPointSet->points[i].z = Point.GetZ();
			PCLPointSet->points[i].r = 255;
			PCLPointSet->points[i].g = 255;
			PCLPointSet->points[i].b = 255;
		}
		vioFilePath2PointCloud.insert(make_pair(FileName, PCLPointSet));

		std::string DxfPath = FilePath.substr(0, FilePath.length() - 3) + "dxf";
		std::vector<std::vector<Point2D>> RoadData;
		std::pair<Point2D, Point2D> AABBOfRoad;
		CDXFReader DXFReader;
		DXFReader.loadDXF(DxfPath, RoadData);
		AABBOfRoad = DXFReader.getAABB();

		std::shared_ptr<CPointCloudHandler> pPointCloudHandler;
		CGALPointSetType OriginCGALPointCloud;
		convertPointCloudFromPCL2CGAL(PCLPointSet, OriginCGALPointCloud);
		pPointCloudHandler->simplifyPointCloud(OriginCGALPointCloud);

		CGALPointSetType AddPointSet;
		for (auto Road : RoadData)
		{
			CGALPointSetType CurrentAddPoint(pPointCloudHandler->process(Road, OriginCGALPointCloud, AABBOfRoad));
			AddPointSet.join(CurrentAddPoint);
		}
		emit FinishLoadPointCloud(FileName, PCLPointSet, OriginCGALPointCloud, AddPointSet);
	}
	emit FinishLoadAllPointCloud();
}

